package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"runtime"
	"time"
)

// 配置结构体
type Config struct {
	AppID       string `json:"app_id"`
	AppSecret   string `json:"app_secret"`
	AdminMobile string `json:"admin_mobile,omitempty"` // 管理员手机号（可选）
}

// 认证响应结构体
type AuthResponse struct {
	Code              int    `json:"code"`
	Msg               string `json:"msg"`
	TenantAccessToken string `json:"tenant_access_token"`
	Expire            int    `json:"expire"`
}

// 创建文档请求结构体
type CreateDocRequest struct {
	FolderToken string `json:"folder_token,omitempty"` // 父文件夹的token，可选
	Title       string `json:"title"`                  // 文档标题
}

// 创建文档响应结构体
type CreateDocResponse struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data struct {
		Document struct {
			DocumentID string `json:"document_id"`
			RevisionID int    `json:"revision_id"`
			Title      string `json:"title"`
		} `json:"document"`
	} `json:"data"`
}

// 添加文档内容请求结构体
type AddBlockRequest struct {
	Children []Block `json:"children"`
	Index    int     `json:"index,omitempty"`
}

// 文档块结构体
type Block struct {
	BlockType int         `json:"block_type"`
	Text      interface{} `json:"text,omitempty"`
}

// 文本内容结构体
type TextContent struct {
	Elements []TextElement `json:"elements"`
	Style    *Style        `json:"style,omitempty"`
}

// 文本元素结构体
type TextElement struct {
	TextRun *TextRun `json:"text_run,omitempty"`
}

// 文本运行结构体
type TextRun struct {
	Content string `json:"content"`
}

// 样式结构体
type Style struct {
	Bold   bool `json:"bold,omitempty"`
	Italic bool `json:"italic,omitempty"`
}

// 添加协作者请求结构体
type AddMemberRequest struct {
	MemberType string `json:"member_type"` // "openid", "email", etc.
	MemberID   string `json:"member_id"`   // 用户ID
	Perm       string `json:"perm"`        // "view", "edit", "full_access"
	PermType   string `json:"perm_type"`   // "container", "single_page"
	Type       string `json:"type"`        // "user", "chat", "department", "group"
}

// 飞书文档客户端
type FeishuDocClient struct {
	config      Config
	accessToken string
	httpClient  *http.Client
}

// 创建新的飞书文档客户端
func NewFeishuDocClient(config Config) *FeishuDocClient {
	return &FeishuDocClient{
		config:     config,
		httpClient: &http.Client{},
	}
}

// 获取访问令牌
func (c *FeishuDocClient) GetAccessToken() error {
	url := "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"

	payload := map[string]string{
		"app_id":     c.config.AppID,
		"app_secret": c.config.AppSecret,
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal payload error: %v", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("create request error: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("request error: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read response error: %v", err)
	}

	var authResp AuthResponse
	if err := json.Unmarshal(body, &authResp); err != nil {
		return fmt.Errorf("unmarshal response error: %v", err)
	}

	if authResp.Code != 0 {
		return fmt.Errorf("get access token failed: %s", authResp.Msg)
	}

	c.accessToken = authResp.TenantAccessToken
	return nil
}

// 创建文档
func (c *FeishuDocClient) CreateDocument(title string, folderToken string) (*CreateDocResponse, error) {
	if c.accessToken == "" {
		return nil, fmt.Errorf("access token is empty, please get access token first")
	}

	url := "https://open.feishu.cn/open-apis/docx/v1/documents"

	payload := CreateDocRequest{
		Title:       title,
		FolderToken: folderToken,
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return nil, fmt.Errorf("marshal payload error: %v", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("create request error: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+c.accessToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request error: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read response error: %v", err)
	}

	var createResp CreateDocResponse
	if err := json.Unmarshal(body, &createResp); err != nil {
		return nil, fmt.Errorf("unmarshal response error: %v", err)
	}

	if createResp.Code != 0 {
		return nil, fmt.Errorf("create document failed: %s", createResp.Msg)
	}

	return &createResp, nil
}

// 向文档批量添加文本块
func (c *FeishuDocClient) AddTextBlocks(documentID string, contents []string) error {
	if c.accessToken == "" {
		return fmt.Errorf("access token is empty, please get access token first")
	}

	url := fmt.Sprintf("https://open.feishu.cn/open-apis/docx/v1/documents/%s/blocks/%s/children", documentID, documentID)

	// 创建所有文本块
	children := make([]Block, 0, len(contents))
	for _, content := range contents {
		block := Block{
			BlockType: 2, // 2 表示文本块
			Text: &TextContent{
				Elements: []TextElement{
					{
						TextRun: &TextRun{
							Content: content,
						},
					},
				},
				Style: &Style{},
			},
		}
		children = append(children, block)
	}

	payload := AddBlockRequest{
		Children: children,
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal payload error: %v", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("create request error: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+c.accessToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("request error: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read response error: %v", err)
	}

	if resp.StatusCode == 429 {
		// 遇到频率限制，等待后重试
		time.Sleep(1 * time.Second)
		return c.AddTextBlocks(documentID, contents)
	}

	if resp.StatusCode != 200 {
		return fmt.Errorf("HTTP error %d: %s", resp.StatusCode, string(body))
	}

	if len(body) == 0 {
		return nil // 空响应表示成功
	}

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("unmarshal response error: %v", err)
	}

	if code, ok := result["code"].(float64); !ok || code != 0 {
		return fmt.Errorf("add text block failed: %s", result["msg"])
	}

	return nil
}

// 设置文档公开权限（任何人可编辑）
func (c *FeishuDocClient) SetDocumentPublicPermission(documentID string) error {
	if c.accessToken == "" {
		return fmt.Errorf("access token is empty, please get access token first")
	}

	// 使用云空间权限API来设置文档权限
	url := fmt.Sprintf("https://open.feishu.cn/open-apis/drive/v1/permissions/%s/public?type=docx", documentID)

	// 设置为企业内任何人可编辑
	payload := map[string]interface{}{
		"external_access":   false,
		"link_share_entity": "tenant_editable",
		"share_entity":      "anyone",
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal payload error: %v", err)
	}

	req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("create request error: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+c.accessToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("request error: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read response error: %v", err)
	}

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("unmarshal response error: %v", err)
	}

	if code, ok := result["code"].(float64); !ok || code != 0 {
		return fmt.Errorf("set permission failed: %s", result["msg"])
	}

	return nil
}

// 添加用户作为文档管理员
func (c *FeishuDocClient) AddDocumentAdmin(documentID, userID string) error {
	if c.accessToken == "" {
		return fmt.Errorf("access token is empty, please get access token first")
	}

	if userID == "" {
		return nil // 如果用户ID为空，跳过添加管理员
	}

	url := fmt.Sprintf("https://open.feishu.cn/open-apis/drive/v1/permissions/%s/members?type=docx", documentID)

	payload := AddMemberRequest{
		MemberType: "openid",
		MemberID:   userID,
		Perm:       "full_access", // 管理员权限
		PermType:   "container",
		Type:       "user",
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal payload error: %v", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("create request error: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+c.accessToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("request error: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read response error: %v", err)
	}

	if resp.StatusCode != 200 {
		return fmt.Errorf("HTTP error %d: %s", resp.StatusCode, string(body))
	}

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("unmarshal response error: %v", err)
	}

	if code, ok := result["code"].(float64); !ok || code != 0 {
		return fmt.Errorf("add admin failed: %s", result["msg"])
	}

	return nil
}

// 通过手机号获取用户OpenID
func (c *FeishuDocClient) GetUserOpenID(mobile string) (string, error) {
	if c.accessToken == "" {
		return "", fmt.Errorf("access token is empty, please get access token first")
	}

	url := "https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id?user_id_type=open_id"

	if mobile == "" {
		return "", fmt.Errorf("手机号不能为空")
	}

	// 构建请求体
	requestBody := map[string]interface{}{
		"mobiles":          []string{mobile},
		"include_resigned": true, // 包含离职用户
	}

	jsonData, err := json.Marshal(requestBody)
	if err != nil {
		return "", fmt.Errorf("marshal request error: %v", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("create request error: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+c.accessToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("request error: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("read response error: %v", err)
	}

	if resp.StatusCode != 200 {
		return "", fmt.Errorf("HTTP error %d: %s", resp.StatusCode, string(body))
	}

	var result struct {
		Code int    `json:"code"`
		Msg  string `json:"msg"`
		Data struct {
			UserList []map[string]interface{} `json:"user_list"`
		} `json:"data"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return "", fmt.Errorf("unmarshal response error: %v", err)
	}

	if result.Code != 0 {
		return "", fmt.Errorf("get user openid failed: %s", result.Msg)
	}

	if len(result.Data.UserList) == 0 {
		return "", fmt.Errorf("未找到手机号为 %s 的用户", mobile)
	}

	// 检查第一个用户的ID字段
	user := result.Data.UserList[0]

	// 尝试不同的可能字段名
	var userID string
	if id, ok := user["user_id"].(string); ok && id != "" {
		userID = id
	} else if id, ok := user["open_id"].(string); ok && id != "" {
		userID = id
	} else if id, ok := user["union_id"].(string); ok && id != "" {
		userID = id
	}

	if userID == "" {
		return "", fmt.Errorf("找到手机号 %s 对应的用户，但无法获取用户ID", mobile)
	}

	return userID, nil
}

// 从环境变量加载配置
func loadConfigFromEnv() (Config, error) {
	var config Config

	config.AppID = os.Getenv("FEISHU_APP_ID")
	config.AppSecret = os.Getenv("FEISHU_APP_SECRET")
	config.AdminMobile = os.Getenv("FEISHU_ADMIN_MOBILE")

	if config.AppID == "" {
		return config, fmt.Errorf("环境变量 FEISHU_APP_ID 未设置")
	}

	if config.AppSecret == "" {
		return config, fmt.Errorf("环境变量 FEISHU_APP_SECRET 未设置")
	}

	return config, nil
}

// 从配置文件加载配置（保留作为备用选项）
func loadConfigFromFile(configPath string) (Config, error) {
	var config Config

	file, err := os.Open(configPath)
	if err != nil {
		return config, fmt.Errorf("open config file error: %v", err)
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	if err := decoder.Decode(&config); err != nil {
		return config, fmt.Errorf("decode config error: %v", err)
	}

	return config, nil
}

// 使用默认浏览器打开URL
func openURL(url string) error {
	var cmd string
	var args []string

	switch runtime.GOOS {
	case "windows":
		cmd = "rundll32"
		args = []string{"url.dll,FileProtocolHandler", url}
	case "darwin":
		cmd = "open"
		args = []string{url}
	case "linux":
		cmd = "xdg-open"
		args = []string{url}
	default:
		return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
	}

	return exec.Command(cmd, args...).Start()
}

func main() {
	// 优先从环境变量加载配置
	config, err := loadConfigFromEnv()
	if err != nil {
		// 如果环境变量未设置，尝试从配置文件加载
		configPath := "config.json"
		if len(os.Args) > 1 {
			configPath = os.Args[1]
		}
		
		config, err = loadConfigFromFile(configPath)
		if err != nil {
			fmt.Printf("配置加载失败: %v\n", err)
			return
		}
	}

	// 创建飞书文档客户端
	client := NewFeishuDocClient(config)

	// 获取访问令牌
	if err := client.GetAccessToken(); err != nil {
		fmt.Printf("获取访问令牌失败: %v\n", err)
		return
	}

	// 创建文档（使用默认标题）
	title := " "
	
	docResp, err := client.CreateDocument(title, "")
	if err != nil {
		fmt.Printf("创建文档失败: %v\n", err)
		return
	}

	documentID := docResp.Data.Document.DocumentID

	// 如果指定了管理员，添加为管理员
	var adminUserID string
	if config.AdminMobile != "" {
		var err error
		adminUserID, err = client.GetUserOpenID(config.AdminMobile)
		if err != nil {
			fmt.Printf("查询用户失败: %v\n", err)
		} else {
			if err := client.AddDocumentAdmin(documentID, adminUserID); err != nil {
				fmt.Printf("添加管理员失败: %v\n", err)
			}
		}
	}

	// 构建文档链接并用默认浏览器打开
	docURL := fmt.Sprintf("https://feishu.cn/docx/%s", documentID)
	fmt.Printf("文档链接: %s\n", docURL)

	if err := openURL(docURL); err != nil {
		fmt.Printf("打开浏览器失败: %v\n", err)
	}
}
